Skip to main content

Integrating with Webhooks

Listen for messages about radom payments and orders associated with your seller wallet address so your integration can automatically trigger reactions.

How Radom uses webhooks

Radom uses webhooks to provide real-time information about all on-chain Radom smart contract activity. This enables sellers to create integrations for synchronization of the state of their products and subscriptions with purchaser configuration and funding.

Radom sends messages via POST request to webhooks registered by a seller. For each message, the seller wallet address is used to determine the webhook to which the message is sent.

For each message that is not confirmed to be sent successfully, Radom will attempt retries every 20 minutes for 3 hours. If Radom detects the webhook as offline for 1 day, message failure retries are disabled. If a webhook is paused then messages will not be sent, but they will be saved as webhook failures to be sent later. If a webhook is offline or paused for over 30 days messages will not be sent and additionally webhook failures will no longer be saved.

Webhook message object

{
"eventName": "order.purchased",
"blockNumber": 135,
"transactionHash": "0xf2702815c6c769d198d1c753e09840e9c4af775c94ad32293a0fb8cb0db3ee0c",
"transactionTimestamp": 1676613942,
"sellerAddress": "0xb946ea0de6c749ac6999c0fc6e8f415bdd052338",
"customerAddress": "0xb946ea0de6c749ac6999c0fc6e8f415bdd052338",
"orderHash": "biH6Vm1PMrzFVNYkQ/VUmVMEMA8OWANUvNgnaoOgOOw=",
"subscriptions": [
{
"subscriptionId": 2,
"subscriptionEnd": 1721012742
}
],
"chainId": 31337,
"paymentToken": "0x0000000000000000000000000000000000000000",
"paymentAmount": "0.0",
"metadata": [
{
"key": "radom-metadata",
"value": {
"paymentLinkOrderId": "570c8e91-3345-494b-8a72-553fbd274e3a"
}
}
]
}

Steps to receive webhook messages

  1. Create a webhook endpoint to handle POST requests from Radom by returning 200 response status code.
  2. Registering a webhook with publicly accessible URL.
  3. Identify and resend webhook message failures.
  4. Update or pause a webhook.

1. Create a webhook HTTPS endpoint

Create a web application with a webhook endpoint. The endpoint should respond to a POST request which handles the message object data delivered in a JSON payload. The endpoint must respond with HTTP 200 status code.

The header should be checked for a verification_key, which will be randomly generated and provided when registering a webhook.

Below is some sample code to help get started with receiving POST requests from Radom:

// Installation:
// cargo add actix-web reqwest anyhow serde serde_json --features serde/derive
use actix_web::{
http::header::HeaderName, web, App, HttpRequest, HttpResponse, HttpServer, Responder,
};
use serde::{Deserialize, Serialize};
use std::{net::TcpListener};

static RADOM_VERIFICATION_KEY: &str = "OGFiNjRlODMtNDAzZC00OGMyLWEzNWMtMTRmNjk1ZGIwYWNjMHhiOTQ2ZWEwZGU2Yzc0OWFjNjk5OWMwZmM2ZThmNDE1YmRkMDUyMzM4";

#[actix_web::main]
async fn main() -> Result<(), std::io::Error> {
let listener = TcpListener::bind("localhost:5000")?;
let server = HttpServer::new(move || {
App::new()
.route("/webhook_endpoint", web::post().to(handle_post))
.route("/", web::post().to(handle_post))
})
.listen(listener)?
.run();
server.await
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct Subscription {
subscription_id: u64,
subscription_end: u64,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct MetadataValue {
#[serde(skip_serializing_if = "Option::is_none")]
payment_link_order_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
payment_link_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
invoice_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
checkout_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
product_ids: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct Metadata {
key: String,
value: MetadataValue,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct WebhookMessage {
event_name: String,
block_number: u64,
transaction_hash: String,
transaction_timestamp: u64,
seller_address: String,
customer_address: String,
payment_hash: Option<String>,
order_hash: Option<String>,
subscriptions: Option<Vec<Subscription>>,
chain_id: u64,
payment_token: String,
payment_amount: String,
metadata: Vec<Metadata>,
}

async fn handle_post(req: HttpRequest, body: web::Json<WebhookMessage>) -> impl Responder {
println!("Received POST request");
let radom_verification_key = HeaderName::from_lowercase(b"radom-verification-key").unwrap();
match req.headers().get(radom_verification_key) {
Some(v) => {
if v != RADOM_VERIFICATION_KEY {
return HttpResponse::BadRequest().finish();
}
}
None => return HttpResponse::BadRequest().finish(),
}
if let Ok(json) = serde_json::to_string_pretty(&body) {
println!("{json}");
}
HttpResponse::Ok().finish()
}

2. Register a webhook

Use the Developer Section in the Radom Dashboard configuration in the Radom dashboard to register the URL of your server running your webhook application. Alternatively, create the webhook through the API.

3. Handle webhook message failures

Use the Developer Section in the Radom Dashboard configuration in the Radom dashboard to reset webhook failures so that Radom will attempt to send the messages again. This can be done for all or individual webhook failures. Alternatively, resend all webhook failures for a webhook, or resend individual webhook failures through the API.

Webhook behavior

Resending webhook failures will disable the offline flag on the webhook.

4. Updating and pausing a webhook

Use the Developer Section in the Radom Dashboard configuration in the Radom dashboard to update a webhook. Alternatively, update the webhook ​through the API.